package com.hans.scala.ImplicitConversion

/**
  * 隐式转换
  * scalac -Xprint:typper
  */
package demo {
  package util {

    import java.util.Date
    import java.text.SimpleDateFormat

    object DateUtil {

      implicit def toDateWrapper(date: Date) = new DateWrapper(date)

      class DateWrapper(date: Date) {
        def format(str: String) = new SimpleDateFormat(str).format(date)
      }

    }

  }

  package service {

    import java.text.SimpleDateFormat
    import java.util.Date

    // 注： 必须将object Rest的定义放在class Rest之前，或者显式指出str2Date的返回类型,否则编译不通过
    object Rest {

      implicit def str2Date(str: String): RichDate = new RichDate(str)

      class RichDate(str: String) {
        def toDate() = new SimpleDateFormat("yyyy-MM-dd").parse(str)
      }

    }

    class Rest {

      import util.DateUtil.toDateWrapper
      import Rest.str2Date

      // 必须把demo.util包下的伴随对象DateWrapper中的所有成员引进来
      def today() = new Date().format("yyyy-MM-dd")

      // 伴随对象 Rest中定义了一个隐式转换函数
      def getDate(str: String): Date = str.toDate()
    }

  }

  package str {

    class StringWrapper(str: String) {
      def extractUpperChar = str.foldLeft("") {
        (s: String, c: Char) => if (c.isUpper) s + c else s
      }
    }

    object StringWrapper {
      implicit def toStringWrapper(str: String): StringWrapper = new StringWrapper(str)

      //  implicit def toStringWrapper(str: String) = str.foldLeft("") {
      //    (s: String, c: Char) => if (c.isUpper) s + c else s
      //  }
    }

  }

  package human {

    class Car {
      def driveFast() {
        println("car reach destination fast.")
      }
    }

    //    object ManUtil {
    //      implicit def addCarTool(m: Man) = new Car()
    //    }
    class Person {
      def walk() {
        println("person can walk.")
      }
    }

    class Man extends Person {
      def run() {
        println("man can run.")
      }
    }

  }

}

object ImplicitConversionExample {
  def main(args: Array[String]) {
    import demo.service.Rest
    println(new Rest().today())
    println(new Rest().getDate("2011-01-09"))

    import demo.str.StringWrapper.toStringWrapper
    println("Implicit Conversion Example".extractUpperChar)

    import demo.human._
    //    import demo.human.ManUtil.addCarTool
    implicit def addCarTool(m: Man) = new Car()

    val m = new Man()
    m.driveFast()
    m.walk()
  }
}
